package com.chuangyiruanke.util;

import com.sun.istack.internal.NotNull;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by zxh on 17/1/2.
 */
public class StringUtils extends org.apache.commons.lang3.StringUtils {
    private static final Pattern numberPattern = Pattern.compile("^[0-9]+$");
    private static final Pattern characterPattern = Pattern.compile("^[0-9a-zA-Z]+$");
    private static final Pattern phonePattern = Pattern.compile("^1[3-9][0-9]{9}$");
    private static final Pattern emailPattern = Pattern.compile("^[a-zA-Z0-9_.\\-]+@[a-zA-Z0-9_\\-]+(\\.[a-zA-Z0-9_\\-]+)+$");
    private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    @NotNull
    public static String toHexString(byte[] byteArray) {
        if (byteArray == null) {
            return "";
        }
        StringBuilder builder = new StringBuilder(byteArray.length * 2);
        for (byte a : byteArray) {
            builder.append(HEX[(a >> 4) & 0xf]);
            builder.append(HEX[a & 0xf]);
        }
        return builder.toString();
    }

    @NotNull
    public static byte[] toByteArray(String hexString) {
        if (StringUtils.isNullOrEmpty(hexString)) {
            return new byte[0];
        }
        int len = hexString.length();
        byte[] data = new byte[len / 2 + (len & 1)];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = Short.valueOf(hexString.substring(i, (i + 2) > len ? (i + 1) : (i + 2)), 16).byteValue();
        }
        return data;
    }

    public static byte[] computePassword(RefValue<Integer> salt, String password) {
        salt.value = new Random().nextInt();
        return computePassword(salt.value, password);
    }

    public static byte[] computePassword(int salt, String password) {
        return getSha1(String.format("%s%d", password, salt));
    }

    public static byte[] computePassword(String password) {
        return getSha1(password);
    }

    @NotNull
    public static String getMD5(String str) {
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(str.getBytes(StandardCharsets.UTF_8));
            byte[] bytes = mdTemp.digest();
            return toHexString(bytes);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static byte[] getSha1(String str) {
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes(StandardCharsets.UTF_8));
            return mdTemp.digest();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static boolean isEmail(String email) {
        Matcher matcher = emailPattern.matcher(email);
        return matcher.find();
    }

    public static boolean isNotBlank(String value) {
        return !isNullOrEmpty(value);
    }

    public static boolean isNullOrEmpty(String value) {
        return value == null || value.length() == 0;
    }

    public static boolean isPhone(String phone) {
        Matcher matcher = phonePattern.matcher(phone);
        return matcher.find();
    }

    public static String join(String join, String[] strAry) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < strAry.length; i++) {
            if (i == (strAry.length - 1)) {
                sb.append(strAry[i]);
            } else {
                sb.append(strAry[i]).append(join);
            }
        }

        return new String(sb);
    }

    public static int compare(String str1, String str2) {
        if (str1 != null && str2 != null) {
            return str1.compareTo(str2);
        } else {
            return str1 == null && str2 == null ? 0 : str1 == null ? -1 : 1;
        }
    }

    public static int compareIgnoreCase(String str1, String str2) {
        if (str1 != null && str2 != null) {
            return str1.compareToIgnoreCase(str2);
        } else {
            return str1 == null && str2 == null ? 0 : str1 == null ? -1 : 1;
        }
    }

    public static Byte[] spitToByteArray(String str, String separator) throws NumberFormatException {
        if (isNullOrEmpty(str)) {
            return new Byte[0];
        }
        String[] array = splitByWholeSeparator(str, separator);
        Byte[] result = new Byte[array.length];
        int index = 0;
        for (String val : array) {
            result[index++] = Byte.valueOf(val);
        }
        return result;
    }

    public static Integer[] spitToIntegerArray(String str, String separator) throws NumberFormatException {
        if (isNullOrEmpty(str)) {
            return new Integer[0];
        }
        String[] array = splitByWholeSeparator(str, separator);
        Integer[] result = new Integer[array.length];
        int index = 0;
        for (String val : array) {
            result[index++] = Integer.valueOf(val);
        }
        return result;
    }

    public static Long[] spitToLongArray(String str, String separator) throws NumberFormatException {
        if (isNullOrEmpty(str)) {
            return new Long[0];
        }
        String[] array = splitByWholeSeparator(str, separator);
        Long[] result = new Long[array.length];
        int index = 0;
        for (String val : array) {
            result[index++] = Long.valueOf(val);
        }
        return result;
    }

    public static Short[] splitToShortArray(String str, String separator) throws NumberFormatException {
        if (isNullOrEmpty(str)) {
            return new Short[0];
        }
        String[] array = splitByWholeSeparator(str, separator);
        Short[] result = new Short[array.length];
        int index = 0;
        for (String val : array) {
            result[index++] = Short.valueOf(val);
        }
        return result;
    }

    /**
     * 验证文本是否由指定长度的数字组成
     *
     * @param text   需验证的文本
     * @param length 文本长度
     */
    public static void verifyNumberString(String text, int length, String tipName) {
        if (text == null || text.length() != length) {
            throw new IllegalArgumentException(String.format(Locale.CHINESE, "输入的%s无效，必须由%d位数字组成", tipName, length));
        }
        Matcher matcher = numberPattern.matcher(text);
        if (!matcher.matches()) {
            throw new IllegalArgumentException(String.format(Locale.CHINESE, "输入的%s无效，必须由%d位数字、大小写字母组成", tipName, length));
        }
    }

    /**
     * 验证文本是否由指定长度的数字及大小写字母组成
     *
     * @param text   需验证的文本
     * @param length 文本长度
     */
    public static void verifyCharactedString(String text, int length, String tipName) {
        if (text == null || text.length() != length) {
            throw new IllegalArgumentException(String.format(Locale.CHINESE, "输入的%s无效，必须由%d位数字、大小写字母组成", tipName, length));
        }
        Matcher matcher = characterPattern.matcher(text);
        if (!matcher.matches()) {
            throw new IllegalArgumentException(String.format(Locale.CHINESE, "输入的%s无效，必须由%d位数字、大小写字母组成", tipName, length));
        }
    }
}
